package com.hengpeng.common.web.tags;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyContent;

import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;

import com.hengpeng.common.acl.vo.ButtonObject;
import com.hengpeng.common.util.StringHelper;
import com.hengpeng.common.web.annotation.HtmlInput;
import com.hengpeng.common.web.annotation.HtmlInputType;
import com.hengpeng.common.web.tags.vo.PropertyConfig;

/**
 * <pre>
 * 由集合自动创建列表的标签
 * </pre>
 * @author linriqing
 * @version 1.0, 2006-6-16
 */
public class ListTag extends ButtonContainerTag
{
	/**
	 * <pre>
	 * 分页信息
	 * </pre>
	 * @author linriqing
	 * @version 1.0, 2010-8-12
	 */
	public static class Pagination
	{

		public int currentPage = 1;

		public int entityCount = 0;

		public int pageCount = 0;

		public int pageSize = 15;

		public Pagination(HttpServletRequest request, final String... listname)
		{
			String listName = "";
			if (listname.length == 0)
			{
				listName = request.getParameter(TagConstant.REQUEST_PARAMETERNAME_PAGINATION_CURRENTPAGEINDEX);
			}
			else
			{
				listName = listname[0];
			}
			String currentPage = request.getParameter(TagConstant.REQUEST_PARAMETERNAME_PAGINATION_CURRENTPAGEINDEX
					+ "4" + listName);
			this.currentPage = currentPage == null ? 1 : NumberUtils.toInt(currentPage);
			String pageSize = request.getParameter(TagConstant.REQUEST_PARAMETERNAME_PAGINATION_PAGESIZE + "4"
					+ listName);
			if (!StringHelper.isEmpty(pageSize))
			{
				int int1 = NumberUtils.toInt(pageSize);
				if (int1 > 0)
				{
					this.pageSize = int1;
				}
			}
		}

		/**
		 * 构造函数
		 * @param entityCount 总记录数
		 * @param pageSize 每页显示记录数
		 */
		public Pagination(int entityCount, int pageSize)
		{
			this.entityCount = entityCount;
			if (pageSize > 0)
			{
				this.pageSize = pageSize;
			}
			this.pageCount = entityCount % pageSize == 0 ? entityCount / this.pageSize : entityCount / this.pageSize
					+ 1;
			if (pageCount == 0)
			{
				pageCount = 1;
			}
		}

		public void setEntityCount(int entityCount)
		{
			this.entityCount = entityCount;
			this.pageCount = this.entityCount % this.pageSize == 0 ? this.entityCount / this.pageSize
					: this.entityCount / this.pageSize + 1;
			if (pageCount == 0)
			{
				pageCount = 1;
			}
		}

		public void setPageSize(int pageSize)
		{
			if (pageSize > 0)
			{
				this.pageSize = pageSize;
			}
		}
	}

	private static final long serialVersionUID = -5415000370631477211L;

	private boolean allowSort;

	private String collection;

	private String createLink;

	private String deleteLink;

	private String detailLink;

	private String excludeFields;

	private String fieldWidth;

	private String fieldAlign;

	private String includeFields;

	private String linkTarget;

	private boolean needTitle = true;

	private String paginationName;

	private boolean showCheckBox;

	private String showLinkField;

	private String title;

	private String type;

	private String updateLink;

	@Override
	public int doAfterBody() throws JspException
	{
		super.doAfterBody();
		BodyContent body = this.getBodyContent();
		String customButton = body.getString();
		body.clearBody();
		try
		{
			StringBuffer content = new StringBuffer();
			if (collection != null)
			{
				HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
				renderCollection(customButton, content, request, request.getContextPath() + "/", pageContext);
			}
			getPreviousOut().print(content.toString());
		}
		catch (IOException e)
		{
			throw new JspException(e);
		}
		catch (IllegalAccessException e)
		{
			throw new JspException(e);
		}
		catch (ClassNotFoundException e)
		{
			throw new JspException(e);
		}
		return SKIP_BODY;
	}

	public int doStartTag() throws JspException
	{
		super.doStartTag();
		return EVAL_BODY_BUFFERED;
	}

	public String getCollection()
	{
		return collection;
	}

	public String getCreateLink()
	{
		return createLink;
	}

	public String getDeleteLink()
	{
		return deleteLink;
	}

	public String getDetailLink()
	{
		return detailLink;
	}

	public String getExcludeFields()
	{
		return excludeFields;
	}

	public String getFieldWidth()
	{
		return fieldWidth;
	}

	public String getFieldAlign()
	{
		return fieldAlign;
	}

	public String getIncludeFields()
	{
		return includeFields;
	}

	public String getLinkTarget()
	{
		return linkTarget;
	}

	public String getPaginationName()
	{
		return paginationName;
	}

	public String getShowLinkField()
	{
		return showLinkField;
	}

	public String getTab(int tabLayer)
	{
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < tabLayer; i++)
		{
			sb.append("\t");
		}
		return sb.toString();
	}

	public String getTitle()
	{
		return title;
	}

	public String getType()
	{
		return type;
	}

	public String getUpdateLink()
	{
		return updateLink;
	}

	public boolean isAllowSort()
	{
		return allowSort;
	}

	private boolean isChecked(Object selectValue, String so, PropertyConfig htmlInput, Object inItem)
	{
		boolean isSelected = false;
		if (selectValue != null)
		{
			if (selectValue.getClass().isAssignableFrom(inItem.getClass()))
			{
				if (selectValue.getClass().isArray())
				{
					Object[] itemsArray = (Object[]) selectValue;
					for (int i = 0; i < itemsArray.length; i++)
					{
						Object item = itemsArray[i];
						String sso = wrapperElementValue(item, htmlInput);
						if (sso.equalsIgnoreCase(so))
						{
							isSelected = true;
							break;
						}
					}
				}
				else if (selectValue instanceof Collection<?>)
				{
					final Collection<?> optionCollection = (Collection<?>) selectValue;
					for (Iterator<?> it = optionCollection.iterator(); it.hasNext();)
					{
						Object item = it.next();
						String sso = wrapperElementValue(item, htmlInput);
						if (sso.equalsIgnoreCase(so))
						{
							isSelected = true;
							break;
						}
					}
				}
				else if (selectValue instanceof Map<?, ?>)
				{
					final Map<?, ?> optionMap = (Map<?, ?>) selectValue;
					for (Iterator<?> it = optionMap.entrySet().iterator(); it.hasNext();)
					{
						Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
						String sso = wrapperElementValue(entry, htmlInput);
						if (sso.equalsIgnoreCase(so))
						{
							isSelected = true;
							break;
						}
					}
				}
				else
				{
					String sso = wrapperElementValue(selectValue, htmlInput);
					if (sso.equalsIgnoreCase(so))
					{
						isSelected = true;
					}
				}
			}
			else
			{
				String sso = selectValue.toString();
				if (sso.equalsIgnoreCase(so))
				{
					isSelected = true;
				}
			}
		}
		return isSelected;
	}

	public boolean isNeedTitle()
	{
		return needTitle;
	}

	public boolean isShowCheckBox()
	{
		return showCheckBox;
	}

	private String process(String contextPath, String content, final Object value, final List<Field> includeField,
			final Field idField, final String idFieldValue, PageContext pageContext) throws JspException
	{
		// String url = (String) evaluate(content, String.class, pageContext);
		String url = ConvertParameter.convert(content, new ConvertProcessor()
		{
			public String replace(String key)
			{
				if (key.equalsIgnoreCase(idField.getName()))
				{
					return idFieldValue;
				}
				for (Field field : includeField)
				{
					if (key.equalsIgnoreCase(field.getName()))
					{
						HtmlInput htmlInputAnnotation = field.getAnnotation(HtmlInput.class);
						PropertyConfig htmlInput = new PropertyConfig(htmlInputAnnotation);
						try
						{
							return wrapperSimplyValue(field, value, htmlInput, htmlInputAnnotation);
						}
						catch (IllegalAccessException e)
						{
							e.printStackTrace();
						}
					}
				}

				return "{" + key + "}";
			}
		});
		if (url.startsWith("/"))
		{
			url = contextPath + url.substring(1);
		}
		return url;
	}

	public void renderCollection(String customButton, StringBuffer content, HttpServletRequest request,
			String contextPath, PageContext pageContext) throws JspException, IllegalAccessException,
			ClassNotFoundException
	{
		if (!needTitle)
		{
			this.showCheckBox = false;
		}
		Object attribute = request.getAttribute(collection);
		if (Collection.class.isAssignableFrom(attribute.getClass()))
		{
			Class<?> type = Class.forName(this.type);
			List<Field> allField = new ArrayList<Field>();
			// 父类的方法
			while (!type.equals(Object.class))
			{
				Field[] fields = type.getDeclaredFields();
				allField.addAll(Arrays.asList(fields));
				type = type.getSuperclass();
			}
			// 过滤不显示的字段
			List<Field> includeField = new ArrayList<Field>();
			Field idField = null;
			// HtmlInput idHtmlInput = null;
			PropertyConfig idHtmlInput = null;
			Set<Field> configHtmlField = new HashSet<Field>();
			String[] showColumns = request.getParameterValues("showColumns4" + collection + "");
			// 处理需要显示的字段，需要保持原有的字段顺序
			// if ((showColumns != null) && (showColumns.length > 0))
			// {
			// content.append("<script type=\"text/javascript\">\r\n");
			// content.append("</script>\r\n");
			// }
			if ((showColumns != null) && (showColumns.length > 0))
			{
				StringBuffer showColumnsBuffer = new StringBuffer();
				Set<String> showColumnSet = new HashSet<String>();
				for (String string : showColumns)
				{
					if (string.length() > 0)
					{
						showColumnSet.add(string);
					}
				}
				if ((includeFields != null) && (includeFields.length() > 0))
				{
					String[] incColumns = includeFields.split(TagConstant.INPUT_COLLECTION_SPLIT_REGEX);
					for (String string : incColumns)
					{
						if (string.length() > 0)
						{
							if (showColumnSet.contains(string))
							{
								showColumnsBuffer.append(string);
								showColumnsBuffer.append(TagConstant.INPUT_COLLECTION_SPLIT_REGEX);
								showColumnSet.remove(string);
							}
						}
					}
				}
				for (String string : showColumnSet)
				{
					showColumnsBuffer.append(string);
					showColumnsBuffer.append(TagConstant.INPUT_COLLECTION_SPLIT_REGEX);
				}
				includeFields = showColumnsBuffer.toString();
			}

			if ((includeFields != null) && (includeFields.length() > 0))
			{
				String[] split = includeFields.split(TagConstant.INPUT_COLLECTION_SPLIT_REGEX);
				for (String string : split)
				{
					if (string.trim().length() > 0)
					{
						for (Field field : allField)
						{
							if (field.getName().equalsIgnoreCase(string.trim()))
							{
								includeField.add(field);
							}

							field.setAccessible(true);
							HtmlInput htmlInput = field.getAnnotation(HtmlInput.class);
							if (htmlInput != null)
							{
								configHtmlField.add(field);
								if (htmlInput.type().equals(HtmlInputType.ID)
										|| htmlInput.type().equals(HtmlInputType.AUTOID))
								{
									idField = field;
									idHtmlInput = new PropertyConfig(htmlInput);
								}
							}
						}
					}
				}
			}
			else
			{
				for (Field field : allField)
				{
					includeField.add(field);

					field.setAccessible(true);
					HtmlInput htmlInput = field.getAnnotation(HtmlInput.class);
					if (htmlInput != null)
					{
						configHtmlField.add(field);
						if (htmlInput.type().equals(HtmlInputType.ID) || htmlInput.type().equals(HtmlInputType.AUTOID))
						{
							idField = field;
							idHtmlInput = new PropertyConfig(htmlInput);
						}
					}
				}
			}

			String currentpageindex = TagConstant.REQUEST_PARAMETERNAME_PAGINATION_CURRENTPAGEINDEX + "4" + collection;
			content.append("<!-- " + collection + "数据列表开始 -->\r\n");
			// 开始组建js脚本
			// 数据分页js脚本
			content.append("<script type=\"text/javascript\">\r\n");
			if (paginationName != null)
			{
				content.append("// " + collection + "数据列表分页脚本\r\n");
				content.append("function _navigate4" + collection + "(obj, type, pageCount)\r\n");
				content.append("{\r\n");
				content.append("		var currentpage = parseInt(obj.form." + currentpageindex + ".value);\r\n");
				content.append("		switch(type)\r\n");
				content.append("		{\r\n");
				content.append("			case 1:\r\n");
				content.append("				obj.form." + currentpageindex + ".value = 1;\r\n");
				content.append("			    break;\r\n");
				content.append("			case 2:\r\n");
				content.append("				if((currentpage - 1) < 1)\r\n");
				content.append("				{\r\n");
				content.append("					obj.form." + currentpageindex + ".value=1;\r\n");
				content.append("				}\r\n");
				content.append("				else\r\n");
				content.append("				{\r\n");
				content.append("					obj.form." + currentpageindex + ".value = currentpage - 1;\r\n");
				content.append("			    }\r\n");
				content.append("				break;\r\n");
				content.append("			case 3:\r\n");
				content.append("				if((currentpage + 1) >= pageCount)\r\n");
				content.append("				{\r\n");
				content.append("					if(pageCount > 0)\r\n");
				content.append("					{\r\n");
				content.append("						obj.form." + currentpageindex + ".value = pageCount;\r\n");
				content.append("					}\r\n");
				content.append("					else\r\n");
				content.append("					{\r\n");
				content.append("						obj.form." + currentpageindex + ".value = 1;\r\n");
				content.append("					}\r\n");
				content.append("				}\r\n");
				content.append("				else\r\n");
				content.append("				{\r\n");
				content.append("					obj.form." + currentpageindex + ".value = currentpage + 1;\r\n");
				content.append("				}\r\n");
				content.append("			    break;\r\n");
				content.append("			case 4:\r\n");
				content.append("				if(pageCount > 0)\r\n");
				content.append("				{\r\n");
				content.append("					obj.form." + currentpageindex + ".value = pageCount;\r\n");
				content.append("				}\r\n");
				content.append("				else\r\n");
				content.append("				{\r\n");
				content.append("					obj.form." + currentpageindex + ".value = 1;\r\n");
				content.append("				}\r\n");
				content.append("				break;\r\n");
				content.append("			case 5:\r\n");
				content.append("				if(currentpage < 1)\r\n");
				content.append("				{\r\n");
				content.append("					obj.form." + currentpageindex + ".value=1;\r\n");
				content.append("				}\r\n");
				content.append("				else if(currentpage > pageCount)\r\n");
				content.append("				{\r\n");
				content.append("					if(pageCount > 0)\r\n");
				content.append("					{\r\n");
				content.append("						obj.form." + currentpageindex + ".value = pageCount;\r\n");
				content.append("					}\r\n");
				content.append("					else\r\n");
				content.append("					{\r\n");
				content.append("						obj.form." + currentpageindex + ".value = 1;\r\n");
				content.append("					}\r\n");
				content.append("				}\r\n");
				content.append("				break;\r\n");
				content.append("    }\r\n");
				content.append("    if(obj.form.onsubmit){if(obj.form.onsubmit()){obj.form.submit();}}else{obj.form.submit();}\r\n");
				content.append("}\r\n");
			}
			// 数据列表选择框js脚本
			if (showCheckBox)
			{
				content.append("// " + collection + "数据列表选择脚本\r\n");
				content.append("function _select4" + collection + "(obj,type)\r\n");
				content.append("{\r\n");
				content.append("		var names = document.getElementsByName(obj);\r\n");
				content.append("		var len=names.length;\r\n");
				content.append("		if(len>0)\r\n");
				content.append("		{\r\n");
				content.append("		    var i=0;\r\n");
				content.append("		    for(i=0; i<len; i++)\r\n");
				content.append("		    {\r\n");
				content.append("		        if(type==1)\r\n");
				content.append("		        {\r\n");
				content.append("		            names[i].checked=true;\r\n");
				content.append("		        }\r\n");
				content.append("		        else if(type==2)\r\n");
				content.append("		        {\r\n");
				content.append("		            names[i].checked=false;\r\n");
				content.append("		        }\r\n");
				content.append("		        else\r\n");
				content.append("		        {\r\n");
				content.append("					if(names[i].checked)\r\n");
				content.append("						names[i].checked=false;\r\n");
				content.append("					else\r\n");
				content.append("						names[i].checked=true;\r\n");
				content.append("		        }\r\n");
				content.append("		    }\r\n");
				content.append("		}\r\n");
				content.append("}\r\n");
			}
			// 链接和按钮提交js脚本
			if ((this.detailLink != null) || (this.updateLink != null) || (this.deleteLink != null)
					|| (this.getButtons().size() > 0))
			{
				content.append("// " + collection + "数据列表表单提交脚本\r\n");
				content.append("function _submitAction4" + collection + "(obj, action, params)\r\n");
				content.append("{\r\n");
				content.append("		var submitForm;\r\n");
				content.append("		while ((obj.parentNode) && (obj.parentNode.tagName) && (!obj.parentNode.tagName.match(/FORM/i)))\r\n");
				content.append("		{\r\n");
				content.append("			obj = obj.parentNode;\r\n");
				content.append("		}\r\n");
				content.append("		submitForm = obj.parentNode;\r\n");
				content.append("		if(!submitForm)\r\n");
				content.append("		{\r\n");
				content.append("			submitForm = document.createElement(\"form\");\r\n");
				content.append("			document.body.appendChild(submitForm);\r\n");
				content.append("		}\r\n");
				content.append("		if((action!=null)&&(action.length > 0))\r\n");
				content.append("		{\r\n");
				content.append("			submitForm.setAttribute(\"action\", action);\r\n");
				content.append("		}\r\n");
				if (linkTarget != null)
				{
					content.append("		submitForm.setAttribute(\"target\", \"" + this.linkTarget + "\");\r\n");
				}
				content.append("		submitForm.setAttribute(\"method\", \"POST\");\r\n");
				content.append("		for(var key in params)\r\n");
				content.append("		{\r\n");
				content.append("				var hiddenField = document.createElement(\"input\");\r\n");
				content.append("				hiddenField.setAttribute(\"type\", \"hidden\");\r\n");
				content.append("				hiddenField.setAttribute(\"name\", key);\r\n");
				content.append("				hiddenField.setAttribute(\"value\", params[key]);\r\n");
				content.append("				submitForm.appendChild(hiddenField);\r\n");
				content.append("		}\r\n");
				content.append("		submitForm.submit();\r\n");
				content.append("}\r\n");
			}
			content.append("</script>\r\n");
			content.append("<!-- " + collection + "数据列表显示区 -->\r\n");
			content.append("<table class=\"data_table_main\">\r\n");
			if (needTitle)
			{
				content.append("<tr>\r\n<td class=\"data_table_main_td\">\r\n");
				content.append("<!-- " + collection + "数据列表标题头 -->\r\n");
				// 开始组装列表页眉内容
				content.append("<table class=\"data_table_title\">\r\n");
				// 如果需要在页眉显示分页，这里面可以作相应处理
				renderTitle(content, customButton, contextPath, configHtmlField, includeField);
				content.append("</table>\r\n</td>\r\n</tr>\r\n<tr>\r\n<td>\r\n");
				content.append("\r\n<table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\r\n<tr>\r\n<td width=\"8\" background=\""
						+ contextPath + "layout/list/tab_left.gif\">&nbsp;</td>\r\n<td>\r\n");
			}
			else
			{
				content.append("<tr>\r\n<td class=\"data_table_main_td\">\r\n");
			}
			// 自定义每列显示的宽度
			Iterator<String> widthIt = null;
			List<String> asList = null;
			if (fieldWidth != null)
			{
				String[] split = fieldWidth.split(TagConstant.INPUT_COLLECTION_SPLIT_REGEX);
				asList = Arrays.asList(split);
			}
			if (asList != null)
			{
				widthIt = asList.iterator();
			}
			// 自定义每列的对齐方式
			Iterator<String> alignIt = null;
			List<String> alignList = null;
			if (fieldAlign != null)
			{
				String[] split = fieldAlign.split(TagConstant.INPUT_COLLECTION_SPLIT_REGEX);
				alignList = Arrays.asList(split);
			}
			if (alignList != null)
			{
				alignIt = alignList.iterator();
			}

			content.append("\r\n<!-- " + collection + "数据列表数据区 -->\r\n");
			content.append("<table  id=\"main_table4" + collection + "\" class=\"data_table_list\">\r\n");
			// 组装列表头部信息
			renderHeader(content, includeField, widthIt, alignIt);
			// 开始组装列表数据区
			final Collection<?> values = (Collection<?>) attribute;
			Iterator<?> iterator = values.iterator();
			if (iterator.hasNext())
			{
				Object value = iterator.next();
				if (asList != null)
				{
					widthIt = asList.iterator();
				}
				if (alignList != null)
				{
					alignIt = alignList.iterator();
				}
				// 逐笔记录进行显示
				renderSingleRow(content, request, value, allField, includeField, idField, idHtmlInput, widthIt,
						alignIt, contextPath, deleteLink, updateLink, linkTarget, detailLink, showLinkField,
						showCheckBox, pageContext);
				while (iterator.hasNext())
				{
					Object object = (Object) iterator.next();
					if (asList != null)
					{
						widthIt = asList.iterator();
					}
					if (alignList != null)
					{
						alignIt = alignList.iterator();
					}
					renderSingleRow(content, request, object, allField, includeField, idField, idHtmlInput, widthIt,
							alignIt, contextPath, deleteLink, updateLink, linkTarget, detailLink, showLinkField,
							showCheckBox, pageContext);
				}
			}
			content.append("</table>\r\n");
			if (needTitle)
			{
				content.append("</td>\r\n<td width=\"8\" background=\"" + contextPath
						+ "layout/list/tab_right.gif\">&nbsp;</td> </tr>\r\n</table>");
				content.append("\r\n</td>\r\n</tr>\r\n<tr>\r\n<td background=\"" + contextPath
						+ "layout/list/tab_bottom.gif\">\r\n");
				content.append("\r\n<!-- " + collection + "数据列表分页按钮 -->\r\n");
				// 組裝頁腳分页数据
				// 首先生成分页信息对象
				Pagination parameterObject = null;
				String strPageSize = null;
				String strCurrentPage = null;
				if (paginationName != null)
				{
					parameterObject = (Pagination) request.getAttribute(paginationName);
					if (parameterObject != null)
					{
						strPageSize = parameterObject.pageSize + "";
						strCurrentPage = parameterObject.currentPage + "";
					}
				}
				content.append(renderPaginationButton(request, customButton, currentpageindex, parameterObject,
						strPageSize, strCurrentPage, contextPath));
			}
			content.append("</td>\r\n</tr>\r\n</table>\r\n");
			content.append("<script type=\"text/javascript\">\r\n ");
			content.append("	new ResizeWidget('main_table4" + collection + "');\r\n");
			content.append("</script>\r\n");
			content.append("<!-- " + collection + "数据列表结束 -->\r\n");
		}
	}

	private String renderElement(Object selectValue, String so, PropertyConfig htmlInput, Object item)
			throws JspException
	{
		StringBuffer string = new StringBuffer();
		if (isChecked(selectValue, so, htmlInput, item))
		{
			// string.append(so).append(TagConstant.INPUT_COLLECTION_SPLIT_REGEX);
			String valueProperty = htmlInput.valueProperty();
			if ((htmlInput.labelProperty() != null) && (htmlInput.labelProperty().length() > 0))
			{
				valueProperty = htmlInput.labelProperty();
			}
			if (valueProperty != null && valueProperty.trim().length() > 0)
			{
				BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(item);
				string.append(wrapper.getPropertyValue(valueProperty)).append(TagConstant.INPUT_COLLECTION_SPLIT_REGEX);
			}

		}
		return string.toString();
	}

	public void renderHeader(StringBuffer content, List<Field> includeField, Iterator<String> widthIt,
			Iterator<String> alignIt)
	{
		content.append("<tr class=\"data_list_tr\">\r\n");

		if (showCheckBox)
		{
			content.append("<th class=\"data_list_th\" style=\"width:40px\">").append("选择").append("</th>\r\n");
		}
		for (Field field : includeField)
		{
			field.setAccessible(true);
			HtmlInput htmlInputAnnotation = field.getAnnotation(HtmlInput.class);
			PropertyConfig htmlInput = new PropertyConfig(htmlInputAnnotation);
			if (htmlInput != null)
			{
				// 拼接单元格样式
				String fieldStyle = "";
				// 宽度
				if ((widthIt != null) && (widthIt.hasNext()))
				{
					String str = widthIt.next();
					if (!"".equals(str))
					{
						fieldStyle += "width: " + str + "px;";
					}
				}
				// 对齐方式
				if ((alignIt != null) && (alignIt.hasNext()))
				{
					String str = alignIt.next();
					if (!"".equals(str))
					{
						fieldStyle += "text-align: " + str + ";";
					}
				}
				if (!"".equals(fieldStyle))
				{
					if (allowSort)
					{
						content.append("<th class=\"data_list_th\" style=\"" + fieldStyle + "\">")
								.append("<a href=\"javascript:void(_sort4" + collection + "('" + field.getName()
										+ "'))\">").append(htmlInput.label()).append("</a></th>\r\n");
					}
					else
					{
						content.append("<th class=\"data_list_th\" style=\"" + fieldStyle + "\">")
								.append(htmlInput.label()).append("</th>\r\n");
					}
				}
				else
				{
					if (allowSort)
					{
						content.append("<th class=\"data_list_th\">")
								.append("<a href=\"javascript:void(_sort4" + collection + "('" + field.getName()
										+ "'))\">").append(htmlInput.label()).append("</a></th>\r\n");
					}
					else
					{
						content.append("<th class=\"data_list_th\">").append(htmlInput.label()).append("</th>\r\n");
					}
				}
			}
		}
		if ((updateLink != null) || (deleteLink != null) || ((this.detailLink != null) && (showLinkField == null))
				|| (this.getButtons().size() > 0))
		{
			content.append("<th class=\"data_list_th\" style=\"width:120px\">操作</th>\r\n");
		}
		content.append("</tr>\r\n");
	}

	/**
	 * <pre>
	 * 根据总页码、当前页码显示分页导航按钮。
	 * </pre>
	 * @param request http请求对象
	 * @param customButton 定制的按钮
	 * @param currentpageindex 当前页控件名称
	 * @param pagination 分页信息
	 * @param strPageSize
	 * @param strCurrentPage
	 * @param contextPath 应用根目录
	 * @return 分页导航按钮
	 */
	public String renderPaginationButton(HttpServletRequest request, String customButton, String currentpageindex,
			Pagination pagination, String strPageSize, String strCurrentPage, String contextPath)
	{
		StringBuffer content = new StringBuffer();
		content.append("<table class=\"data_table_pagination\" align='center'>\r\n");
		content.append("<tr><td width=\"12\" height=\"35\"><img src=\"" + contextPath
				+ "layout/list/tab_left_bottom.gif\" width=\"12\" height=\"35\" /></td>");
		content.append("<td align='left'>\r\n");
		if (isShowCheckBox())
		{
			renderSelectLabel(content);
			content.append("&nbsp;&nbsp;");
			content.append(customButton);
		}
		else
		{
			content.append("&nbsp;&nbsp;");
		}
		content.append("</td>");

		if (pagination != null)
		{
			int pageSize = pagination.pageSize;
			int currentPage = 1;
			if (strPageSize != null)
			{
				pageSize = Integer.parseInt(strPageSize);
			}
			if (strCurrentPage != null)
			{
				currentPage = Integer.parseInt(strCurrentPage);
			}
			content.append("<td align='right'>\r\n");
			content.append("共<b>");
			content.append(pagination.entityCount);
			content.append("</b>条记录,");
			content.append("当前第<b>");
			content.append(currentPage);
			content.append("</b>页/共<b>");
			content.append(pagination.pageCount);
			content.append("</b>页 &nbsp;&nbsp;");
			content.append("每页");
			content.append("<input type=\"text\" class=\"data_table_pagination_input\" name=\"");
			content.append(TagConstant.REQUEST_PARAMETERNAME_PAGINATION_PAGESIZE + "4" + collection);
			content.append("\"  size=\"2\" maxlength=\"3\" value=\"");
			content.append(pageSize);
			content.append("\" />条记录\r\n");
			content.append("<button type=\"button\" class=\"data_table_pagination_button\" onclick=\"javascript:_navigate4"
					+ collection + "(this, 1, ");
			content.append(pagination.pageCount);
			content.append(");\" >首页</button>\r\n");
			content.append("<button type=\"button\" class=\"data_table_pagination_button\" onclick=\"javascript:_navigate4"
					+ collection + "(this, 2, ");
			content.append(pagination.pageCount);
			content.append(");\" >上页</button>\r\n");
			content.append("<button type=\"button\" class=\"data_table_pagination_button\" onclick=\"javascript:_navigate4"
					+ collection + "(this, 3, ");
			content.append(pagination.pageCount);
			content.append(");\" >下页</button>\r\n");
			content.append("<button type=\"button\" class=\"data_table_pagination_button\" onclick=\"javascript:_navigate4"
					+ collection + "(this, 4, ");
			content.append(pagination.pageCount);
			content.append(");\" >末页</button>\r\n");
			content.append("&nbsp;&nbsp;转到第<input class=\"data_table_pagination_input\" type=\"text\" size=\"3\" name=\"");
			content.append(currentpageindex);
			content.append("\" value=\"");
			content.append(currentPage);
			content.append("\" onkeyup=\"value=value.replace(/[^\\d]/g,'');\" />页\r\n");
			content.append("<button type=\"button\" class=\"data_table_pagination_button\" onclick=\"javascript:_navigate4"
					+ collection + "(this, 5, ");
			content.append(pagination.pageCount);
			content.append(");\" >GO</button>\r\n");
			content.append("</td>");
		}
		content.append("<td width=\"16\"><img src=\""
				+ contextPath
				+ "layout/list/tab_right_bottom.gif\" width=\"16\" height=\"35\" /></td></tr></table><input type=\"hidden\" name=\""
				+ TagConstant.REQUEST_PARAMETERNAME_PAGINATION_CURRENTPAGEINDEX + "\" value=\"" + collection
				+ "\" />\r\n");
		return content.toString();
	}

	private void renderSelectLabel(StringBuffer sb)
	{
		sb.append("选择: <a href=\"javascript:void(_select4" + collection + "('id4" + collection + "',1))\">全选</a>");
		sb.append(", <a href=\"javascript:void(_select4" + collection + "('id4" + collection + "',2))\">不选</a>");
		sb.append(", <a href=\"javascript:void(_select4" + collection + "('id4" + collection + "',3))\">反选</a>");
	}

	public void renderSingleRow(StringBuffer content, HttpServletRequest request, Object value, List<Field> allField,
			List<Field> includeField, Field idField, PropertyConfig idHtmlInput, Iterator<String> widthIt,
			Iterator<String> alignIt, String contextPath, String deleteLink, String updateLink, String linkTarget,
			String detailLink, String showLinkField, boolean showCheckBox, PageContext pageContext)
			throws JspException, IllegalAccessException
	{
		if (value != null)
		{
			content.append("<tr class=\"data_list_tr\">\r\n");
			String idValue = null;

			if (idField != null)
			{
				HtmlInput htmlInputAnnotation = idField.getAnnotation(HtmlInput.class);
				idValue = wrapperSimplyValue(idField, value, idHtmlInput, htmlInputAnnotation);
			}
			if (showCheckBox)
			{
				content.append("<td class=\"data_list_td\">");
				content.append("<input id=\"id4" + collection + "\" type=\"checkbox\" name=\"id4" + collection
						+ "\" value='" + idValue + "' />");
				content.append("</td>\r\n");
			}
			for (Field field : includeField)
			{
				field.setAccessible(true);
				HtmlInput htmlInputAnnotation = field.getAnnotation(HtmlInput.class);
				PropertyConfig htmlInput = new PropertyConfig(htmlInputAnnotation);
				String fieldValue = "";
				if (htmlInput != null)
				{
					String itemsName = htmlInput.items();
					switch (htmlInput.type())
					{
						case CHECKBOX:
						case RADIOBOX:
						case SELECT:
							Object attribute = null;
							if ((itemsName != null) && (itemsName.length() > 0))
							{
								attribute = request.getAttribute(itemsName);
							}
							fieldValue = wrapperMultipleValue(field, value, htmlInput, attribute).toString();
							break;
						case LABEL:
						case TEXTAREA:
						case PASSWORD:
						case PASSWORD_REPEAT:
						case TEXT:
						case HIDDEN:
						case ID:
						case AUTOID:
						default:
							fieldValue = wrapperSimplyShowValue(field, value, htmlInput, null);
							break;
					}
				}
				// 拼接单元格样式
				String fieldStyle = "";
				if ((alignIt != null) && (alignIt.hasNext()))
				{
					String str = alignIt.next();
					if (!"".equals(str))
					{
						fieldStyle += "text-align: " + str + ";";
					}
				}
				// 加入单元格样式
				if (!"".equals(fieldStyle))
				{
					content.append("<td class=\"data_list_td\" title=\"" + fieldValue + "\" style=\"" + fieldStyle
							+ "\">");
				}
				else
				{
					content.append("<td class=\"data_list_td\" title=\"" + fieldValue + "\">");
				}
				boolean showLink = false;
				if (showLinkField != null)
				{
					if (field.getName().equalsIgnoreCase(showLinkField.trim()))
					{
						showLink = true;
					}
				}
				if (htmlInput != null)
				{
					String processLink = null;
					if ((showLink) && (idValue != null) && (detailLink != null))
					{
						processLink = process(contextPath, detailLink, value, allField, idField, idValue, pageContext);
					}
					switch (htmlInput.type())
					{
						case CHECKBOX:
						case RADIOBOX:
						case SELECT:
							if (processLink != null)
							{
								content.append("<a href=\"javascript:void(0)\" onclick=\"javascript:void(_submitAction4"
										+ collection
										+ "(this,'"
										+ getUrlByLink(processLink)
										+ "',"
										+ getUrlParamByLink(processLink) + "));return false;\" ");
								content.append(">");
								content.append(fieldValue);
								content.append("</a>");
							}
							else
							{
								content.append(fieldValue);
							}
							break;
						case LABEL:
						case TEXTAREA:
						case PASSWORD:
						case PASSWORD_REPEAT:
						case TEXT:
						case HIDDEN:
						case ID:
						case AUTOID:
						default:
							if (processLink != null)
							{
								content.append("<a href=\"javascript:void(0)\" onclick=\"javascript:void(_submitAction4"
										+ collection
										+ "(this,'"
										+ getUrlByLink(processLink)
										+ "',"
										+ getUrlParamByLink(processLink) + "));return false;\" ");
								content.append(">");
								content.append(fieldValue);
								content.append("</a>");
							}
							else
							{
								content.append(fieldValue);
							}
							break;
					}
				}
				content.append("</td>\r\n");
			}
			if ((updateLink != null) || (deleteLink != null) || ((this.detailLink != null) && (showLinkField == null))
					|| (this.getButtons().size() > 0))
			{
				content.append("<td class=\"data_list_td\">");
				if (detailLink != null)
				{
					if (idValue != null)
					{
						if (showLinkField == null)
						{
							String processLink = process(contextPath, detailLink, value, allField, idField, idValue,
									pageContext);
							content.append("<img src=\""
									+ contextPath
									+ "layout/list/detail.gif\" width=\"16\" height=\"16\" /><a href=\"javascript:void(0)\" onclick=\"javascript:void(_submitAction4"
									+ collection + "(this,'" + getUrlByLink(processLink) + "',"
									+ getUrlParamByLink(processLink) + "));return false;\" ");
							content.append(">详细</a>&nbsp;&nbsp;");
						}
					}
				}
				if (updateLink != null)
				{
					if (idValue != null)
					{
						String processLink = process(contextPath, updateLink, value, allField, idField, idValue,
								pageContext);
						content.append("<img src=\""
								+ contextPath
								+ "layout/list/edit.gif\" width=\"16\" height=\"16\" /><a href=\"javascript:void(0)\" onclick=\"javascript:void(_submitAction4"
								+ collection + "(this,'" + getUrlByLink(processLink) + "',"
								+ getUrlParamByLink(processLink) + "));return false;\" ");
						content.append(">编辑</a>&nbsp;&nbsp;");
					}
				}
				if (deleteLink != null)
				{
					if (idValue != null)
					{
						String processLink = process(contextPath, deleteLink, value, allField, idField, idValue,
								pageContext);
						content.append("<img src=\""
								+ contextPath
								+ "layout/list/delete.gif\" width=\"16\" height=\"16\" /><a href=\"javascript:void(0)\" onclick=\"javascript:if(confirm('确定要删除记录吗，删除后将无法恢复？')){void(_submitAction4"
								+ collection + "(this,'" + getUrlByLink(processLink) + "',"
								+ getUrlParamByLink(processLink) + "));return false;}\" ");
						content.append(">删除</a>&nbsp;&nbsp;");
					}
				}
				List<ButtonObject> buttons = this.getButtons();
				for (ButtonObject buttonTag : buttons)
				{
					String processLink = process(contextPath, buttonTag.getDestination(), value, allField, idField,
							idValue, pageContext);
					String customEvent = "true";
					if ((buttonTag.getEvent() != null) && (buttonTag.getEvent().length() > 0))
					{
						customEvent = process(contextPath, buttonTag.getEvent(), value, allField, idField, idValue,
								pageContext);
					}
					if (buttonTag.getImage() != null)
					{
						content.append("<img src=\"" + contextPath + buttonTag.getImage()
								+ "\" width=\"16\" height=\"16\" />");
					}
					content.append("<a href=\"javascript:void(0)\" onclick=\"javascript:if(" + customEvent
							+ "){void(_submitAction4" + collection + "(this,'" + getUrlByLink(processLink) + "',"
							+ getUrlParamByLink(processLink) + "));return false;}\" ");
					if (buttonTag.getDescription() != null)
					{
						content.append(" title=\"" + buttonTag.getDescription() + "\" ");
					}
					content.append(" >" + buttonTag.getShowText() + "</a>&nbsp;&nbsp;");
				}
				content.append("</td>\r\n");
			}
			content.append("</tr>\r\n");
		}
	}

	public void renderTitle(StringBuffer content, String customButton, String contextPath, Set<Field> configHtmlField,
			List<Field> includeField)
	{
		content.append("<tr>\r\n<td width=\"12\" height=\"30\"><img src=\"" + contextPath
				+ "layout/list/tab_left_top.gif\" width=\"12\" height=\"30\" /></td><td align='left'>");
		content.append("<img src=\"" + contextPath + "layout/list/list.gif\" width=\"16\" height=\"16\" />");
		content.append(title);
		content.append("</td>\r\n");
		if (this.createLink != null)
		{
			content.append("<td align=\"right\" nowrap=\"nowrap\">\r\n");
			String processLink = contextPath + "" + this.createLink;
			content.append("<img src=\""
					+ contextPath
					+ "layout/list/create.gif\" width=\"16\" height=\"16\" /><a href=\"javascript:void(0)\" onclick=\"javascript:void(_submitAction4"
					+ collection + "(this,'" + getUrlByLink(processLink) + "'," + getUrlParamByLink(processLink)
					+ "));return false;\" ");
			content.append(">新增</a>");
			content.append("\r\n</td>");
		}
		// 输出显示列调整
		// 字段显示顺序排序
		Comparator<Field> c = new Comparator<Field>()
		{
			@Override
			public int compare(Field o1, Field o2)
			{
				o1.setAccessible(true);
				o2.setAccessible(true);
				HtmlInput htmlInput1 = o1.getAnnotation(HtmlInput.class);
				HtmlInput htmlInput2 = o2.getAnnotation(HtmlInput.class);
				if ((htmlInput1 != null) && (htmlInput2 != null))
				{
					return htmlInput1.index() - htmlInput2.index();
				}
				else
				{
					return 0;
				}
			}
		};
		List<Field> orderConfigHtmlFieldList = new ArrayList<Field>();
		orderConfigHtmlFieldList.addAll(configHtmlField);
		Collections.sort(orderConfigHtmlFieldList, c);
		content.append("<td align=\"left\" width=\"20\"><div id=\"columnsDiv\">\r\n");
		content.append("<span class=\"tips\">\r\n<a href=\"javascript:void(0)\"><img src=\""
				+ contextPath
				+ "layout/list/custom_columns.png\" width=\"16\" height=\"16\" title=\"自定义显示列\" alt=\"自定义显示列\" />\r\n<span class=\"tipsdetails\">\r\n");
		content.append("<div class=\"topbg_tip\"></div>\r\n<div class=\"midbg_tip\">\r\n<span class='cbl'>\r\n");
		content.append("<table width=\"100%\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\r\n<tr>");
		int index = 0;
		Set<String> excludeFieldName = new HashSet<String>();
		if (excludeFields != null)
		{
			excludeFieldName.addAll(Arrays.asList(excludeFields.split(TagConstant.INPUT_COLLECTION_SPLIT_REGEX)));
		}
		for (Field field : orderConfigHtmlFieldList)
		{
			if (!excludeFieldName.contains(field.getName()))
			{
				HtmlInput htmlInputAnnotation = field.getAnnotation(HtmlInput.class);
				PropertyConfig htmlInput = new PropertyConfig(htmlInputAnnotation);
				if (htmlInput != null)
				{
					if (htmlInput.label().length() > 0)
					{
						content.append("<td width=\"50%\" nowrap=\"nowrap\">");
						if (includeField.contains(field))
						{
							content.append("<label title=\"" + htmlInput.label() + "\">\r\n");
							content.append("<input id=\"showColumns4" + collection
									+ "\" type=\"checkbox\" name=\"showColumns4" + collection + "\" value=\""
									+ field.getName() + "\" checked=\"checked\" onclick=\"_checkColumns4" + collection
									+ "('showColumns4" + collection + "')\" />\r\n");
						}
						else
						{
							content.append("<label title=\"" + htmlInput.label() + "\">\r\n");
							content.append("<input id=\"showColumns4" + collection
									+ "\" type=\"checkbox\" name=\"showColumns4" + collection + "\" value=\""
									+ field.getName() + "\" onclick=\"_checkColumns4" + collection + "('showColumns4"
									+ collection + "')\" />\r\n");
						}
						content.append(htmlInput.label());
						content.append("</label>\r\n");
						content.append("</td>");
						if ((index % 2) == 1)
						{
							content.append("</tr><tr>");
						}
						index++;
					}
				}
			}
		}
		content.append("<tr><td colspan=\"2\" align=\"center\">");
		content.append("<script type=\"text/javascript\">\r\n");
		content.append("// " + collection + "数据列表选择脚本\r\n");
		content.append("function _checkColumns4" + collection + "(obj)\r\n");
		content.append("{\r\n");
		content.append("		var names = document.getElementsByName(obj);\r\n");
		content.append("		var len=names.length;\r\n");
		content.append("		if(len>0)\r\n");
		content.append("		{\r\n");
		content.append("		    var i=0;\r\n");
		content.append("		    var count=0;\r\n");
		content.append("		    for(i=0; i<len; i++)\r\n");
		content.append("		    {\r\n");
		content.append("		        if(names[i].checked)\r\n");
		content.append("		        {\r\n");
		content.append("		            count++;\r\n");
		content.append("		        }\r\n");
		content.append("		    }\r\n");
		content.append("		    if(count<1)\r\n");
		content.append("		    {\r\n");
		content.append("		    	alert('至少需要选择一个显示列...');\r\n");
		content.append("		    	names[0].checked=true;\r\n");
		content.append("		    }\r\n");
		content.append("		}\r\n");
		content.append("}\r\n");
		content.append("</script>\r\n");
		content.append("<div class=\"subtag\"><button type=\"submit\"> 确 定 </button></div>");
		content.append("</td></tr></table>");
		content.append("</span></div>\r\n<div class=\"btbg_tip\"></div>\r\n</span>\r\n</a>\r\n</span>");
		content.append("</div></td>\r\n");
		content.append("<td width=\"16\"><img src=\"" + contextPath
				+ "layout/list/tab_right_top.gif\" width=\"16\" height=\"30\" /></td>\r\n");
		content.append("</tr>\r\n");
	}

	public void setAllowSort(boolean allowSort)
	{
		this.allowSort = allowSort;
	}

	public void setCollection(String command)
	{
		this.collection = command;
	}

	public void setCreateLink(String createLink)
	{
		this.createLink = createLink;
	}

	public void setDeleteLink(String deleteLink)
	{
		this.deleteLink = deleteLink;
	}

	public void setDetailLink(String detailLink)
	{
		this.detailLink = detailLink;
	}

	public void setExcludeFields(String excludeFields)
	{
		this.excludeFields = excludeFields;
	}

	public void setFieldWidth(String fieldWidth)
	{
		this.fieldWidth = fieldWidth;
	}

	public void setFieldAlign(String fieldAlign)
	{
		this.fieldAlign = fieldAlign;
	}

	public void setIncludeFields(String exclude)
	{
		this.includeFields = exclude;
	}

	public void setLinkTarget(String detailLinkTarget)
	{
		this.linkTarget = detailLinkTarget;
	}

	public void setNeedTitle(boolean needTitle)
	{
		this.needTitle = needTitle;
	}

	public void setPaginationName(String paginationName)
	{
		this.paginationName = paginationName;
	}

	public void setShowCheckBox(boolean showCheckBox)
	{
		this.showCheckBox = showCheckBox;
	}

	public void setShowLinkField(String linkField)
	{
		this.showLinkField = linkField;
	}

	public void setTitle(String title)
	{
		this.title = title;
	}

	public void setType(String type)
	{
		this.type = type;
	}

	public void setUpdateLink(String updateLink)
	{
		this.updateLink = updateLink;
	}

	protected String wrapperElementValue(Object item, PropertyConfig htmlInput)
	{
		String valueProperty = htmlInput.valueProperty();

		BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(item);
		Object renderValue = new String("");
		if ((valueProperty != null) && (valueProperty.length() > 0))
		{
			renderValue = wrapper.getPropertyValue(valueProperty);
		}
		else if (item instanceof Enum<?>)
		{
			renderValue = ((Enum<?>) item).name();
		}
		else
		{
			renderValue = item;
		}
		return renderValue.toString();
	}

	protected String wrapperElementValue(Map.Entry<?, ?> entry, PropertyConfig htmlInput)
	{
		Object mapKey = entry.getKey();
		BeanWrapper mapKeyWrapper = PropertyAccessorFactory.forBeanPropertyAccess(mapKey);
		String valueProperty = htmlInput.valueProperty();
		Object renderValue = (((valueProperty != null) && (valueProperty.length() > 0)) ? mapKeyWrapper
				.getPropertyValue(valueProperty) : mapKey.toString());
		return renderValue.toString();
	}

	protected String wrapperElementShowValue(Object item, PropertyConfig htmlInput)
	{
		String showValueProperty = htmlInput.valueProperty();
		if ((htmlInput.labelProperty() != null) && (htmlInput.labelProperty().length() > 0)
				&& (!htmlInput.type().equals(HtmlInputType.SELECT)))
		{
			showValueProperty = htmlInput.labelProperty();
		}
		BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(item);
		Object renderValue = new String("");
		if ((showValueProperty != null) && (showValueProperty.length() > 0))
		{
			renderValue = wrapper.getPropertyValue(showValueProperty);
		}
		else if (item instanceof Enum<?>)
		{
			renderValue = ((Enum<?>) item).name();
		}
		else
		{
			renderValue = item;
		}
		return renderValue.toString();
	}

	private StringBuffer wrapperMultipleValue(Field field, Object value, PropertyConfig htmlInput, Object requestItems)
			throws JspException, IllegalArgumentException, IllegalAccessException
	{
		StringBuffer sb = new StringBuffer();
		Object selected = "";
		if (value != null)
		{
			selected = field.get(value);
		}
		Object itemsObject = null;
		if (requestItems != null)
		{
			itemsObject = requestItems;
		}
		Class<?> boundType = field.getType();
		if (itemsObject == null && boundType != null && boundType.isEnum())
		{
			itemsObject = boundType.getEnumConstants();
		}
		if (boundType != null)
		{
			if (boundType.isArray())
			{
				Class<?> componentType = boundType.getComponentType();
				if (itemsObject == null && componentType != null && componentType.isEnum())
				{
					itemsObject = componentType.getEnumConstants();
				}
			}
			else if (Collection.class.isAssignableFrom(boundType))
			{
				Type genericType = field.getGenericType();
				Class<?> componentType = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
				if (itemsObject == null && componentType != null && componentType.isEnum())
				{
					itemsObject = componentType.getEnumConstants();
				}
			}
			else if (Map.class.isAssignableFrom(boundType))
			{
				Type genericType = field.getGenericType();
				Class<?> componentType = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[1];
				if (itemsObject == null && componentType != null && componentType.isEnum())
				{
					itemsObject = componentType.getEnumConstants();
				}
			}
		}
		if (itemsObject != null)
		{
			if (itemsObject.getClass().isArray())
			{
				Object[] itemsArray = (Object[]) itemsObject;
				for (int i = 0; i < itemsArray.length; i++)
				{
					Object item = itemsArray[i];
					String so = wrapperElementValue(item, htmlInput);
					sb.append(renderElement(selected, so, htmlInput, item));
				}
			}
			else if (itemsObject instanceof Collection<?>)
			{
				final Collection<?> optionCollection = (Collection<?>) itemsObject;
				for (Iterator<?> it = optionCollection.iterator(); it.hasNext();)
				{
					Object item = it.next();
					String so = wrapperElementValue(item, htmlInput);
					sb.append(renderElement(selected, so, htmlInput, item));
				}
			}
			else if (itemsObject instanceof Map<?, ?>)
			{
				final Map<?, ?> optionMap = (Map<?, ?>) itemsObject;
				for (Iterator<?> it = optionMap.entrySet().iterator(); it.hasNext();)
				{
					Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
					String so = wrapperElementValue(entry, htmlInput);
					// TODO
					sb.append(renderElement(selected, so, htmlInput, null));
				}
			}
			else
			{
				throw new IllegalArgumentException("Attribute 'items' must be a Collection, an Array or a Map");
			}
		}
		if (sb.length() > 0)
		{
			sb.deleteCharAt(sb.length() - 1);
		}
		return sb;
	}

	protected String wrapperSimplyShowValue(Field field, Object value, PropertyConfig htmlInput, HtmlInput tag)
			throws IllegalAccessException
	{
		Object renderValue = field.get(value);
		String showValue = "";
		if (renderValue != null)
		{
			String pattern = htmlInput.format();
			if ((pattern != null) && pattern.length() > 0)
			{
				Class<?> type = field.getType();
				if (Date.class.isAssignableFrom(type))
				{
					SimpleDateFormat sdf = new SimpleDateFormat(pattern);
					showValue = sdf.format((Date) renderValue);
				}
				else if (Number.class.isAssignableFrom(type))
				{
					DecimalFormat df = new DecimalFormat(pattern);
					showValue = df.format(renderValue);
				}
				else
				{
					MessageFormat mf = new MessageFormat(pattern);
					showValue = mf.format(renderValue);
				}
			}
			else
			{
				showValue = wrapperElementShowValue(renderValue, htmlInput);
			}
		}
		return showValue;
	}

	protected String wrapperSimplyValue(Field field, Object value, PropertyConfig htmlInput, HtmlInput tag)
			throws IllegalAccessException
	{
		Object renderValue = field.get(value);
		String showValue = "";
		if (renderValue != null)
		{
			showValue = renderValue.toString();
		}
		return showValue;
	}
}